package com.starsoft.trade.web;

import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.starsoft.frame.base.service.UserService;
import com.starsoft.frame.core.web.WebUtil;
import com.starsoft.frame.util.DateUtil;
import com.starsoft.frame.util.StringUtil;
import com.starsoft.smdc.bean.SmdcSecurity;
import com.starsoft.smdc.service.HolidayService;
import com.starsoft.trade.bean.TradeAcount;
import com.starsoft.trade.bean.TradeAcountStatus;
import com.starsoft.trade.bean.TradeBill;
import com.starsoft.trade.bean.TradeSummary;
import com.starsoft.trade.service.AcountStatusService;
import com.starsoft.trade.service.TradeAcountService;
import com.starsoft.trade.service.TradeBillService;
import com.starsoft.trade.service.TradeSummaryService;

@RestController
@RequestMapping(value = "/trade/report")
public class AssertReportController {

	@Autowired
	private TradeSummaryService tradeSummaryService;
	@Autowired
	private AcountStatusService acountStatusService;
	@Autowired
	private TradeAcountService tradeAcountService;
	@Autowired
	private HolidayService holidayService;

	@Autowired
	private TradeBillService tradeBillService;

	@RequestMapping(value = "/asset")
	public Map<String, Object> assetReport(HttpServletRequest request) throws Exception {
		if("true".equalsIgnoreCase(request.getParameter("forceRefresh"))){
			Integer acountId = getAcountId(request);
			Date initDate = tradeAcountService.get(acountId).getInitDate();
			acountStatusService.updateStatus(acountId, initDate, null);
		}
		
		Map<String, Object> model = new HashMap<>();
		model.putAll(getStatus(request));
		model.putAll(getChart(request));
		return model;
	}
	
	public Map<String, Object> getChart(HttpServletRequest request) throws Exception {
		Integer acountId = getAcountId(request);

		Date beginDate = getBeginDate(request, acountId);
		Date adjBeginDate = holidayService.getNextBusinessDay(beginDate, -1);
				
		List<TradeSummary> summaryList = tradeSummaryService.getAcountBetween(acountId, adjBeginDate, null);
		TradeSummary summaryBase = summaryList.get(0);
		SmdcSecurity baseIndex = tradeAcountService.getBaseIndex(acountId);

		List<Date> timeLine = new ArrayList<>();
		List<Double> baseProfit = new ArrayList<>();
		List<Double> profit = new ArrayList<>();
		List<Double> asset = new ArrayList<>();
		List<Double> profitMoney = new ArrayList<>();
		List<Double> marketValue = new ArrayList<>();
		for (TradeSummary summary : summaryList) {
			timeLine.add(summary.getId().getAsofdate());
			baseProfit.add(summary.getBaseValue()/summaryBase.getBaseValue()*100-100);
			profit.add((summary.getProfit() - summaryBase.getProfit()) / (summaryBase.getProfit() + 1) * 100);
			asset.add(summary.getNetAssert());
			profitMoney.add(summary.getProfitMoney()-summaryBase.getProfitMoney());
			marketValue.add(summary.getMarketValue());
		}
		
		Map<String, Object> chartResult = new HashMap<>();
		chartResult.put("timeLine", timeLine);
		chartResult.put("baseProfit", baseProfit);
		chartResult.put("profit", profit);
		chartResult.put("asset", asset);
		chartResult.put("profitMoney", profitMoney);
		chartResult.put("marketValue", marketValue);
		chartResult.put("baseIndexName", baseIndex.getSecName());
		Map<String, Object> requestData = new HashMap<String, Object>();
		requestData.put("beginDateType", request.getParameter("beginDateType"));
		requestData.put("beginDate", beginDate);
		chartResult.put("requestData", requestData);
		Map<String, Object> model = new HashMap<>();
		model.put("chart", chartResult);
		return model;
	}
	
	@RequestMapping(value="/getstatus")
	public Map<String, Object> getStatus(HttpServletRequest request) {
		Integer acountId = getAcountId(request);
		Date summaryDate = this.getSummaryDate(request, acountId);

		TradeAcountStatus status;
		if (DateUtil.isToday(summaryDate)) {
			status = acountStatusService.updateStatus(acountId, new Date(), null);
		} else {
			status = acountStatusService.updateAndGet(acountId, summaryDate);
		}

		List<TradeBill> bills = tradeBillService.getBills(acountId, summaryDate);
		List<Map<String, Object>> billsMap = tradeBillService.convertToMap(bills);

		Map<String, Object> statusResult = acountStatusService.convertBean(status);
		statusResult.put("bills", billsMap);
		Map<String, Object> model = new HashMap<>();
		model.put("status", statusResult);
		return model;
	}
	
	private Date getSummaryDate(HttpServletRequest request, Integer acountId){
		TradeAcount tradeAcount = tradeAcountService.get(acountId);
		
		Date summaryDate = WebUtil.getDate(request, "summaryDate", "yyyy-MM-dd");
		String summaryDateType = request.getParameter("summaryDateType");
		if(summaryDate==null){
			summaryDate = new Date();
		}
		if("lastDay".equalsIgnoreCase(summaryDateType)){
			summaryDate = holidayService.getNextBusinessDay(summaryDate, -1);
		} else if("nextDay".equalsIgnoreCase(summaryDateType)){
			summaryDate = holidayService.getNextBusinessDay(summaryDate, 1);
		}
		if(summaryDate.after(new Date())){
			summaryDate = new Date();
		}

		boolean isBusy = holidayService.isBusinessDay(summaryDate);
		if (DateUtil.isToday(summaryDate)){
			boolean isBeforeOpen = holidayService.isBeforeOpen(new Date());
			if(!isBusy || isBeforeOpen) {
				summaryDate = holidayService.getNextBusinessDay(summaryDate, -1);
			}
		} else if(!isBusy){
			summaryDate = holidayService.getNextBusinessDay(summaryDate, -1);
		}
		
		if(tradeAcount.getEndDate()!=null){
			Date endDate = holidayService.getBusinessDay(tradeAcount.getEndDate(), true);
			if(endDate.before(summaryDate)){
				summaryDate = endDate;
			}
		}
		if(tradeAcount.getInitDate()!=null){
			Date startDate = holidayService.getBusinessDay(tradeAcount.getInitDate(), false);
			if(startDate.after(summaryDate)){
				summaryDate = startDate;
			}
		}
		return summaryDate;
	}

	private Date getBeginDate(HttpServletRequest request, Integer acountId) {
		ZonedDateTime now = ZonedDateTime.now();
		String beginDateType = request.getParameter("beginDateType");
		Date beginDate = WebUtil.getDate(request, "beginDate", "yyyy-MM-dd");
		if (!StringUtil.isEmpty(beginDateType)) {
			if ("thisMonth".equalsIgnoreCase(beginDateType)) {
				beginDate = Date.from(now.withDayOfMonth(1).toInstant());
			} else if ("threeMonth".equalsIgnoreCase(beginDateType)) {
				beginDate =  Date.from(now.withDayOfMonth(1).plusMonths(-2).toInstant());
			} else if ("thisYear".equalsIgnoreCase(beginDateType)) {
				beginDate =  Date.from(now.withDayOfYear(1).toInstant());
			} else if ("all".equalsIgnoreCase(beginDateType)) {
				beginDate = null;
			} else {
				beginDate = null;
			}
		} else if (beginDate == null) {
			beginDate = Date.from(now.withDayOfYear(1).toInstant());
		}
		Date initDate = tradeAcountService.get(acountId).getInitDate();
		if ((beginDate != null && beginDate.before(initDate)) || beginDate == null) {
			beginDate = initDate;
		}
		beginDate = holidayService.getBusinessDay(beginDate, false);
		Date nowDate = new Date();
		if(beginDate.after(nowDate) && !DateUtil.isSameDay(beginDate, nowDate)){
			beginDate = holidayService.getNextBusinessDay(nowDate, -1);
		}
		return beginDate;
	}
	
	
	private Integer getAcountId(HttpServletRequest request){
		Integer acountId = null;
		String acountIdStr = request.getParameter("acountId");
		if(StringUtil.isEmpty(acountIdStr)){
			acountId = UserService.getUserContext().getAcountId();
		} else {
			acountId = Integer.parseInt(acountIdStr);
		}
		return acountId;
	}
}
